<?php

class AnHttp
{

    /**
     * @var string HTTP请求类型,curl file_get_contents socket
     */
    static $http_method             = '';

    // * 连接配置  *
    /**
     * @var int cURL执行时间
     */
    static $default_timeout         = 10;

    /**
     * @var int cURL最大链接数
     */
    static $default_max_connects    = 50;

    /**
     * @var int cURL连接时间
     */
    static $default_connect_timeout = 10;

    /**
     * @var string cookie路径
     */
    static $cookie_path             = '';

    /**
     * @var string cookie 文件路径
     */
    static $cookie_file             = '/static/cookie/cookie.file';

    /**
     * @var string SSL 证书路径
     */
    //@Fstatic $SSL_file             = 'D:\kingdisk\coreamp_20101010\htdocs\test\cookie\cacert.pem';

    /**
     * @var string cookie类型：单文件和多文件(按ID，可以是用户户)
     */
    static $cookie_type = 1;

    static $mail = 'fengwx@alltosun.com';

    /**
     * 使用CURL模拟上传文件
     *
     * @param string $file_path     上传文件
     * @param string $opt_url       上传文件位置
     * @param array  $param         cURL参数
     * @return boolean|mixed
     */
    public static function up_file($file_path, $opt_url = '', $param = array())
    {
        if (!file_exists($file_path)) {
            mail(self::$mail, '上传的文件没有权限或不存在');
        }
        $param = self::set_params($param);
        if (!function_exists('curl_init')) {
            mail(self::$mail, 'AnCurl error curl is not exists');
            return false;
        }

        // 发送的文件
        $post_data = array('upload' => "@{$file_path}");

        $ch = curl_init();
        AnCurl::set_curl($ch, $param);
        curl_setopt($ch, CURLOPT_URL, $opt_url);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
        $ret = curl_exec($ch);
        if ($ret === false) {
            mail(self::$mail, 'AnCurl error', var_export(curl_getinfo($ch), true)."\n返回值为false");
        }
        if ($param['debug'] == 1) {
            echo '<pre>';
            echo "\nCURL请求：POST\n";
                echo "\nCURL信息\n";
                var_export(curl_getinfo($ch));
                echo "\n\nCURL参数\n";
                var_export($param);
                echo "\n\n请求数据：\n";
                var_export($file_path);
                echo "\n\n请求结果：\n";
                var_export($ret);
                echo "\n";
        }
        curl_close($ch);
        return $ret;
    }

    public static function down_file($path)
    {
        ;
    }

    /**
     * 初始化
     */
    public static function init_http()
    {
        if (function_exists('curl_init')) {
            self::$http_method = 'curl';
        } else if (function_exists('socket')) {
            self::$http_method = 'socket';
        } else {
            self::$http_method = 'file';
        }
    }

    /**
     * 设置http请求参数
     * @return multitype:number string multitype: unknown
     */
    public static function set_params($param)
    {
        $default = array(
            'connect_timeout' => AnHttp::$default_connect_timeout,
            'timeout'         => AnHttp::$default_timeout,
            'maxconnects'     => AnHttp::$default_max_connects,
            'useragent'       => 'Mozilla/5.0 (Windows NT 6.2) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4',
            'debug'           => 0, // 调试开关
            'header'          => array(),
            'username'        => '',
            'password'        => '',
        );

        if ($param) {
            if (isset($param['useragent'])) {
                $default['useragent'] = $param['useragent'];
            }
            if (isset($param['username'])) {
                $default['username'] = $param['username'];
            }
            if (isset($param['password'])) {
                $default['password'] = $param['password'];
            }
            if (isset($param['header'])) {
                $default['header'] = $param['header'];
            }
            if (isset($param['connect_timeout'])) {
                $default['connect_timeout'] = $param['connect_timeout'];
            }
            if (isset($param['timeout'])) {
                $default['timeout'] = $param['timeout'];
            }
            if (isset($param['referer'])) {
                $default['referer'] = $param['referer'];
            }
            if (isset($param['maxconnects'])) {
                $default['maxconnects'] = $param['maxconnects'];
            }
            if (isset($param['debug'])) {
                $default['debug'] = $param['debug'];
            }
            if (isset($param['cookie'])) {
                $default['cookie'] = $param['cookie'];
            }
        }
        return $default;
    }

    /**
     * POST
     *
     * @param string $url 请求地址
     * @param array $fields 发送数据
     * @param array $param  CURL相关配置
     * array(
     *     'useragent' => string http头中userAgent信息,
     *     'username'  => string 传递一个连接中需要的用户名,
     *     'password'  => string 传递一个连接中需要的密码,
     *     'header'    => array() 设置一个header中传输内容的数组
     * );
     */
    public static function Post($url, $data, $param = array())
    {
        self::init_http();
        $param = self::set_params($param);
        var_dump(self::$http_method);
        echo '<pre>';
        print_r($param);
        if (self::$http_method == 'curl') {
            return AnCurl::post($url, $data, $param);
        } else if (self::$http_method == 'socket') {
            return AnSocket::post($url, $data, $param);
        } else {
            return filegetcontents::post_content($url, $data, $param);
        }
    }

    /**
     *
     * @param string $url   请求地址
     * @param array  $data  get数据
     * @param array  $param 参数
     * @return Ambigous <boolean, Ambigous, multitype:string, mixed, unknown>|string
     */
    public static function Get($url, $data = array(), $param = array())
    {
        self::init_http();;
        $param = AnHttp::set_params($param);
        if (self::$http_method == 'curl') {
            return AnCurl::get($url, $data, $param);
        } else if (self::$http_method == 'curl') {
            return AnSocket::get($url, $data, $param);
        } else {
            return filegetcontents::get_content($url, $data, $param);
        }
    }

    public static function get_cookie_file($id = 0)
    {
        if (self::$cookie_type == 1) {
            return self::$cookie_file;
        } else if(self::$cookie_type == 2) {
            return self::$cookie_file.md5($id);
        }
    }
}

class AnCurl
{
    public static $connect_timeout = 20;
    public static $timeout = 20;
    public static $maxconnects = 49;
    /**
     * 执行cURL
     * @param string $method method 方式 POST、GET
     * @param string $url 请求地址
     * @param array/string $fields 请求的数据
     * @param array  $curl_param
     * @return boolean|multitype:string number |mixed
     */
    private static function execute($method, $url, $fields='', $curl_param)
    {
        $ch = self::create();
        if (false === $ch) {
            if ($method == 'POST') {
                return self::post_content($url, $fields);
            } else {
                return self::get_content($url, $fields);
            }
        }

        if(is_string($url) && strlen($url) && $method != "GET"){
            $ret = curl_setopt($ch, CURLOPT_URL, $url);
        }

        $curl_param = AnHttp::set_params($curl_param);
        // 设置cURL
        self::set_curl($ch, $curl_param);

        // POST
        if('POST' == $method){
            curl_setopt($ch, CURLOPT_POST, true);
//             if(is_array($fields)){
//                 $sets = array();
//                 foreach ($fields as $key => $val){
//                     $sets[] = $key . '=' . urlencode($val);
//                     $sets[$key] = $val;
//                 }
//             }
            curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
        }else if('GET' == $method) {
            // GET
            if (is_array($fields)) {
                $get_str = http_build_query($fields);
            } else {
                $get_str = $fields;
            }
            if (stripos($url, "?") === false) {
                $url .= "?{$get_str}";
            } else {
                $url .= "&{$get_str}";
            }
            $ret = curl_setopt($ch, CURLOPT_URL, $url);
        }

        $ret = self::curl_output($ch, $curl_param, $fields);
        return $ret;
    }

    public static function set_curl($ch, $curl_param)
    {
        // 是否显示头部信息
        curl_setopt($ch, CURLOPT_HEADER, false);
        // 是否将输出结果返回
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        // 编码自动
        curl_setopt($ch, CURLOPT_ENCODING, "");
        // 最大链接数
        curl_setopt($ch, CURLOPT_MAXCONNECTS, $curl_param['maxconnects']);
        // 跟踪跳转
        // curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        // 定义浏览器
        curl_setopt($ch, CURLOPT_USERAGENT, $curl_param['useragent']);
        // 设置curl超时秒数
        curl_setopt($ch, CURLOPT_TIMEOUT, $curl_param['timeout']);
        // 设置CURL连接时间
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $curl_param['connect_timeout']);
        // curl header信息
        if (isset($curl_param['header']) && $curl_param['header']) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $curl_param['header']);
        }
        if (isset($curl_param['referer']) && $curl_param['referer']) {
            curl_setopt ($ch, CURLOPT_REFERER, $curl_param['referer']);
        }

        if(isset($curl_param['username']) && $curl_param['username']){
            curl_setopt($ch, CURLOPT_USERPWD, $curl_param['username'] . ':' . $curl_param['password']);
        }
        // 设置 cookie
        if(isset($curl_param['cookie']) && $curl_param['cookie']){
            curl_setopt($ch, CURLOPT_COOKIE, $curl_param['cookie']);
        }

        if (file_exists(AnHttp::$cookie_file)) {
            curl_setopt($ch, CURLOPT_COOKIEFILE, ROOT.AnHttp::$cookie_file ); //读取
            curl_setopt($ch, CURLOPT_COOKIEJAR, ROOT.AnHttp::$cookie_file ); //保存
        }

    }

    /**
     * cURL模拟POST
     * @param string $url 请求地址
     * @param array $fields 发送数据
     * @param string $userAgent http头中userAgent信息
     * @param array $httpHeaders 设置一个header中传输内容的数组
     * @param string $username 传递一个连接中需要的用户名
     * @param string $password 传递一个连接中需要的密码
     * @return boolean|Ambigous <boolean, multitype:string, multitype:string number , mixed, string>
     */
    public static function post($url, $fields, $param = array())
    {
        $ret = self::execute('POST', $url, $fields, $param);
        if(false === $ret){
            return false;
        }
        return $ret;
    }

    /**
     * cURL模拟GET
     * @param string $url 请求地址
     * @param string $fields 参数
     * @param string $userAgent http头中userAgent信息
     * @param array $httpHeaders 设置一个header中传输内容的数组
     * @param string $username 传递一个连接中需要的用户名
     * @param string $password 传递一个连接中需要的密码
     * @return boolean|Ambigous <boolean, multitype:string, multitype:string number , mixed, string>
     */
    static function get($url, $fields = '', $param = array())
    {
        // get($url, $fields = '', $userAgent = '', $httpHeaders = '', $username = '', $password = '')
        $ret = self::execute('GET', $url, $fields, $param);
        if(false === $ret){
            return false;
        }
        return $ret;
    }

    /**
     * cURL初始化
     * @return boolean|resource
     */
    private static function create()
    {
        $ch = null;
        $ch = curl_init();
        if(!is_resource($ch)){
            return false;
        }
        return $ch;
    }

    /**
     * 下载图片
     * @param string $pic_url    图片地址
     * @param string $file_path  图片路径
     * @param array $params      curl参数
     * @return boolean
     */
    public static function getImg($pic_url, $file_path, $param = array())
    {
        if (!$pic_url) {
            return false;
        }

        /* 取得图片的扩展名，存入变量$ext中 */
        $ext= strrchr($pic_url, ".");
        $ext = strtolower($ext);
        /* 判断是否是合法的图片文件 */
        if(!in_array($ext, array('.jpg', '.jpeg', '.png', '.gif'))){
            return false;
        }
        // 生成唯一的文件
        $file_name = $file_path.(round(microtime(true), 3) * 1000).$ext;
        // Init curl
        $ch = curl_init($pic_url);
        // 创建文件
        $fp = fopen($file_name, "w");
        // 设置http参数
        $curl_param = AnHttp::set_params($param);
        self::set_curl($ch, $curl_param);
        // curl_setopt($ch, CURLOPT_FILE, $pic_url);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        // curl 执行
        $ret = self::curl_output($ch, $curl_param);
        // 将内容写入文件
        fwrite($fp, $ret);
        fclose($fp);
        return $file_path.$file_name;
    }

    /**
     * Curl 执行
     * @param resource $ch curl句柄
     * @param array $curl_param curl参数
     * @return mixed
     */
    public static function curl_output($ch, $curl_param, $data)
    {
        try {
            // 执行cURL
            $ret = curl_exec($ch);
            if ($ret === false) {
                mail(AnHttp::$mail, 'AnCurl error', var_export(curl_getinfo($ch), true)."\n返回值为false");
            }
            if ($curl_param['debug'] == 1) {
                echo '<pre>';
                echo "\n<b>CURL请求：</b>GET\n";
                echo "\n<b>CURL信息</b>\n";
                var_export(curl_getinfo($ch));
                echo "\n\n<b>CURL参数</b>\n";
                var_export($curl_param);
                echo "\n\n<b>请求数据：</b>\n";
                var_export($data);
                echo "\n\n<b>请求结果：</b>\n";
                var_export($ret);
                echo "\n";
            }
        } catch (Exception $e) {
                mail(AnHttp::$mail, 'AnCurl error', "\nAnCurl执行结果".var_export(curl_getinfo($ch), true)."\n报错信息\n".$e->getMessage());
        }
        // curl_errno
        if (curl_errno($ch) == 0){
            return $ret;
        } else if ($curl_param['debug'] == 1) {
            // debug =1 curl 错误代码处理
            require_once './curl_error.php';
            if (isset($curl_error_list[curl_errno($ch)])) {
                return $curl_error_list[curl_errno($ch)];
            } else {
                echo "\n<b>curl_error code</b> \n";
                var_export($ret);
                echo "\n\n";
            }
        }
        curl_close($ch);
        return $ret;
    }
}

/**
 * 调试中……
 * @author fengwx
 *
 */
class AnSocket
{
    /**
     * post
     * @param string $url    url地址
     * @param array  $data   请求数据
     * @param array  $param  配置参数
     */
    public static function post($url, $data, $param = array())
    {
        return self::exec('POST', $url, $data, $param);
    }

    /**
     * get
     * @param string $url    url地址
     * @param array  $data   请求数据
     * @param array  $param  配置参数
     */
    public static function get($url, $data, $param = array())
    {
        return self::exec('GET', $url, $data, $param);
    }

    /**
     * 执行socket
     * @param string $method POST/GET
     * @param string $url    url地址
     * @param array  $data   请求数据
     * @param array  $param  配置参数
     * @return multitype:string |string
     */
    public static function exec($method, $url, $data, $param = array())
    {
        $socket_param = AnHttp::set_params($param);
        // http参数
        $data = http_build_query($data);

        // 解析url
        $url = parse_url($url);

        if ($url['scheme'] != 'http') {
            die('Error: Only HTTP request are supported !');
        }

        // extract host and path:
        $host = $url['host'];
        $path = $url['path'];

        // open a socket connection on port 80 - timeout: 30 sec
        $fp = fsockopen($host, 80, $errno, $errstr, 10);

        if ($fp){

            // send the request headers:
            if ($method == 'GET') {
                fputs($fp, sprintf("GET %s%s%s HTTP/1.0\r\n", $url['path'], $url['query'] ? "?" : $data, $url['query'].'&'.$data));
            } else {
                fputs($fp, sprintf("POST %s%s%s HTTP/1.0\r\n", $url['path'], $url['query'] ? "?" : '', $url['query']));
            }
            fputs($fp, "Host: $host\r\n");

            // referer
            if (isset($socket_param['referer']) && $socket_param['referer'] != '') {
                fputs($fp, "Referer: {$socket_param['referer']}\r\n");
            }
            // cookie
            if (isset($socket_param['cookie']) && $socket_param['cookie'] != '') {
                fputs($fp, "Cookie: {$socket_param['cookie']}\r\n");
            }

            fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
            fputs($fp, "Content-length: ". strlen($data) ."\r\n");
            fputs($fp, "Connection: close\r\n\r\n");
            if ($method == "POST") {
                fputs($fp, $data);
            }

            $result = '';
            while(!feof($fp)) {
                // receive the results of the request
                $result .= fgets($fp, 128);
            }
            var_dump($result);
        }
        else {
            return array(
                'status' => 'err',
                'error' => "$errstr ($errno)"
            );
        }

        // close the socket connection:
        fclose($fp);

        // split the result header from the content
        $result = explode("\r\n\r\n", $result, 2);

        $header = isset($result[0]) ? $result[0] : '';
        $content = isset($result[1]) ? $result[1] : '';

        // return as structured array:
        return $content;
    }

}

/**
 * file_get_contents 模拟post、get
 * @author fengwx
 *
 */
class filegetcontents
{
    /**
     * file_get_contents 模拟POST
     * @param string $url URL地址
     * @param array $post_data 发送的数据
     * @return string
     */
    public static function post_content($url, $post_data, $param = array())
    {
        $context = array();

        if (is_array($post_data)) {
            ksort($post_data);

            if (!isset($param['timeout'])) {
                $param['timeout'] = 10;
            }
            $context['http'] = array (
                    'timeout' => $param['timeout'],
                    'method'  => 'POST',
                    'content' => http_build_query($post_data, '&'),
                    'header' => "Connection: close \r\n".
                    "Content-type: application/x-www-form-urlencoded \r\n",
            );
        }
        return file_get_contents($url, false, stream_context_create($context));
    }

    /**
     * file_get_contents 模拟GET
     * @param string $url URL地址
     * @param array $get_data 请求的数据
     * @return string
     */
    public static function get_content($url, $get_data = array(), $param = array())
    {
        $context = array();

        $context['http']  = array (
                'timeout' => 10,
                'method'  => 'GET'
        );
        if (is_array($get_data)) {
            $content = http_build_query($get_data, '&');
            if ($content && stripos($url, "?") !== false) {
                $url .= "&{$content}";
            } else {
                $url .= "?{$content}";
            }
        }
        return file_get_contents($url, false, stream_context_create($context));
    }
}
?>